package com.gofull.gateway.wechat.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gofull.conn.HttpRequestSimple;
import com.gofull.gateway.wechat.config.WechatConfig;
import com.gofull.gateway.wechat.vo.WechatAccessToken;
import com.gofull.gateway.wechat.vo.WechatJsapiTicket;
import com.gofull.gateway.wechat.vo.WechatTemplate;
import com.shove.Convert;
import com.shove.io.file.PropertyFile;
import com.shove.util.EncryptUtils;
import com.shove.util.ServletUtils;
import com.sp2p.util.DateUtil;

/* *
 *类名：WechatUtils
 *功能：微信接口工具类
 *详细：工具类，可以用作获取access_token、jsapi_ticket等
 *版本：1.0
 *日期：2015-04-29
 *说明：
 *
 */
public class WechatUtils {
	/**
	 * 发送模板信息
	 * 
	 * @param
	 * @return rMap 返回码
	 * @throws Exception
	 */
	public static Map<String,String> sendTemplateMsg(WechatTemplate t){
		Map<String, String> rMap = new HashMap<String, String>();
		String access_token = getAccessToken();
		String requestUrl = WechatConfig.TEMPLATE_URL.replace("ACCESS_TOKEN",
				access_token);
		String templateJson = JSONObject.toJSON(t).toString();

		String resJSON = HttpRequestSimple.getInstance().postSendHttp(
				requestUrl, templateJson);
		JSONObject resObj = JSON.parseObject(resJSON);

		rMap.put("errcode", resObj.getString("errcode"));
		rMap.put("errmsg", resObj.getString("errmsg"));
		rMap.put("msgid", resObj.getString("msgid"));

		return rMap;
	}
	
	/**
	 * 通过OpenID来获取用户基本信息
	 * 
	 * @param
	 * @return userInfoMap
	 * @throws Exception
	 */
	public static Map<String, String> getUserInfoByOpenId(String openid) {
		// 调用接口获取access_token
		String access_token = getAccessToken();
		String infoUrl = WechatConfig.USER_INFO_URL.replace("ACCESS_TOKEN",
				access_token).replace("OPENID", openid);
		Map<String, String> map = new HashMap<String, String>();

		String infoJSON = HttpRequestSimple.getInstance().getSendHttp(infoUrl);
		JSONObject infoObj = JSON.parseObject(infoJSON);
		map.put("subscribe", infoObj.getString("subscribe"));
		map.put("openid", infoObj.getString("openid"));
		map.put("nickname", infoObj.getString("nickname"));
		map.put("sex", infoObj.getString("sex"));
		map.put("province", infoObj.getString("province"));
		map.put("city", infoObj.getString("city"));
		map.put("country", infoObj.getString("country"));
		map.put("language", infoObj.getString("language"));
		map.put("headimgurl", infoObj.getString("headimgurl"));
		map.put("subscribe_time", infoObj.getString("subscribe_time"));
		map.put("unionid", infoObj.getString("unionid"));
		map.put("remark", infoObj.getString("remark"));
		map.put("groupid", infoObj.getString("groupid"));
		map.put("errcode", infoObj.getString("errcode"));
		map.put("errmsg", infoObj.getString("errmsg"));

		return map;
	}
	
	
	/**
	 * 通过code换取网页授权access_token,并拉取用户信息
	 * 
	 * @param
	 * @return userInfoMap
	 * @throws Exception
	 */
	public static Map<String, String> getOauth2UserInfo(String accessToken,
			String openid, String code) {

		Map<String, String> map = new HashMap<String, String>();

		// 调用接口拉取用户信息
		String infoUrl = WechatConfig.GET_SNSAPI_USERINFO_URL.replace(
				"ACCESS_TOKEN", accessToken).replace("OPENID", openid);
		String infoJSON = HttpRequestSimple.getInstance().getSendHttp(infoUrl);
		JSONObject infoObj = JSON.parseObject(infoJSON);

		map.put("openid", infoObj.getString("openid"));
		map.put("nickname", infoObj.getString("nickname"));
		map.put("sex", infoObj.getString("sex"));
		map.put("province", infoObj.getString("province"));
		map.put("city", infoObj.getString("city"));
		map.put("country", infoObj.getString("country"));
		map.put("headimgurl", infoObj.getString("headimgurl"));
		map.put("privilege", infoObj.getString("privilege"));
		map.put("unionid", infoObj.getString("unionid"));
		map.put("errcode", infoObj.getString("errcode"));
		map.put("errmsg", infoObj.getString("errmsg"));

		return map;
	}
	
	/**
	 * 通过code换取网页授权access_token
	 * 
	 * @param
	 * @return access_token
	 * @throws Exception
	 */
	public static Map<String,String> getOauth2AccessToken(String appid,String appsecret,String code) {
		// 调用接口获取access_token
		String url = WechatConfig.OAUTH2_ACCESS_TOKEN_URL.replace("APPID",
				appid).replace("SECRET", appsecret).replace("CODE", code);
		String resJSON = HttpRequestSimple.getInstance().getSendHttp(url);
		JSONObject reqObj = JSON.parseObject(resJSON);
		
		Map<String,String> map = new HashMap<String, String>();
		map.put("access_token",reqObj.getString("access_token"));
		map.put("expires_in",reqObj.getString("expires_in"));
		map.put("refresh_token",reqObj.getString("refresh_token"));
		map.put("openid",reqObj.getString("openid"));
		map.put("scope",reqObj.getString("scope"));
		map.put("unionid",reqObj.getString("unionid"));
		map.put("errcode",reqObj.getString("errcode"));
		map.put("errmsg",reqObj.getString("errmsg"));
		return map;
	}

	/**
	 * 初始化调用JS-SDK参数，wx.config用到
	 * 
	 * @param request
	 *            URL参数列表
	 * @return JS-SDK参数Map
	 * @throws Exception
	 */
	public static Map<String, String> jSdkConfig(HttpServletRequest request) {
		String url = getRequestURL(request);

		Map<String, String> map = new HashMap<String, String>();
		long timestamp = new Date().getTime();
		String nonceStr = getNoncestr();
		String signature = getSignature(nonceStr, timestamp, url);

		map.put("appId", WechatConfig.APPID);
		map.put("timestamp", timestamp + "");
		map.put("nonceStr", nonceStr);
		map.put("signature", signature);

		return map;
	}
	
	public static Map<String, String> jSdkConfig(String url) {
		Map<String, String> map = new HashMap<String, String>();
		long timestamp = new Date().getTime();
		String nonceStr = getNoncestr();
		String signature = getSignature(nonceStr, timestamp, url);

		map.put("appId", WechatConfig.APPID);
		map.put("timestamp", timestamp + "");
		map.put("nonceStr", nonceStr);
		map.put("signature", signature);

		return map;
	}

	/**
	 * 获取微信当前访问的完整URL
	 * 
	 * @param request
	 *            URL参数列表
	 * @return 微信当前访问的完整URL
	 * @throws Exception
	 */
	private static String getRequestURL(HttpServletRequest request) {
		String url = ServletUtils.serverUrl();
		url = url.substring(0, url.length() - 1); // 去除最后“/”符号
		url = url + request.getServletPath() + "?";
		// 获取参数列表
		Map<String, Object> pramsMap = ServletUtils.getPrams(request);
		Collection<String> keyset= pramsMap.keySet();  
	    List<String> list = new ArrayList<String>(keyset);
	    //对key键值按字典升序排序  
	    Collections.sort(list); 
	    for (int i = 0; i < list.size(); i++) { 
	    	if(!list.get(i).equals("from") && !list.get(i).equals("isappinstalled")){
	    		url = url + list.get(i) + "=" + pramsMap.get(list.get(i)) + "&";
	    	}
	    }

		url = url.substring(0, url.length() - 1); // 去除最后“&”符号
		if (pramsMap.get("from") != null) {
			url = url + "&from=" + pramsMap.get("from");
		}

		if (pramsMap.get("isappinstalled") != null) {
			url = url + "&isappinstalled=" + pramsMap.get("isappinstalled");
		}

		System.out.println("=========>url:" + url);
		return url;
	}

	/**
	 * 根据当前访问的完整URL完成签名
	 * 
	 * @param noncestr
	 *            随机字符串
	 * @param timestamp
	 *            时间戳
	 * @param url
	 *            当前访问的完整URL
	 * @return 签名串
	 * @throws Exception
	 */
	public static String getSignature(String noncestr, long timestamp,
			String url) {
		Map<String, String> paMap = new HashMap<String, String>();
		paMap.put("noncestr", noncestr);
		paMap.put("jsapi_ticket", getJsapiTicket());
		paMap.put("timestamp", timestamp + "");
		paMap.put("url", url);

		// 待签名参数按照字段名的ASCII 码从小到大排序（字典序）
		String[] paramKeyArray = new String[] { "noncestr", "jsapi_ticket",
				"timestamp", "url" };
		Arrays.sort(paramKeyArray);

		String paramStr = "";
		for (int i = 0; i < paramKeyArray.length; i++) {
			String key = paramKeyArray[i];
			String value = paMap.get(key);
			paramStr += key + "=" + value + "&";
		}
		paramStr = paramStr.substring(0, paramStr.length() - 1);
		// System.out.println("=========>paramStr:" + paramStr);
		String signature = EncryptUtils.sha(paramStr.toString().trim());
		return signature;
	}

	/**
	 * 生成随机字符串
	 * 
	 * @return 随机字符串
	 * @throws Exception
	 */
	public static String getNoncestr() {
		// length表示生成字符串的长度
		int length = 32;
		String base = "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * 获取微信access_token
	 * 
	 * @param
	 * @return access_token
	 * @throws Exception
	 */
	public static String getAccessToken() {
		PropertyFile pf = new PropertyFile();
		String access_token = pf.read("access_token");
		String access_token_deadTime = pf.read("access_token_deadTime");

		Date deadTime = DateUtil.strToDate(access_token_deadTime);
		long times = DateUtil.remainDateToStringOther(new Date(), deadTime);
		// System.out.println("=========>times:" + times);
		// access_token已过期
		if (times <= 0) {
			WechatAccessToken at = refreshAccessToken();
			access_token = at.getAccess_token();
		}

		return access_token;
	}

	/**
	 * 刷新微信access_token
	 * 
	 * @param
	 * @return access_token
	 * @throws Exception
	 */
	public static WechatAccessToken refreshAccessToken() {
		// 调用接口获取access_token
		WechatAccessToken access_token = new WechatAccessToken();
		String resJSON = HttpRequestSimple.getInstance().getSendHttp(
				WechatConfig.GET_ACCESS_TOKEN_URL);
		JSONObject reqObj = JSON.parseObject(resJSON);
		access_token.setAccess_token(reqObj.getString("access_token"));
		access_token.setExpires_in(reqObj.getString("expires_in"));

		// 计算access_token过期时间
		int expires_in = Convert.strToInt(access_token.getExpires_in(), 0);
		Date deadTime = DateUtil.dateAddSecond(new Date(), expires_in);
		String access_token_deadTime = DateUtil.dateToString(deadTime);

		// 存储access_token信息
		PropertyFile pf = new PropertyFile();
		pf.write("access_token", access_token.getAccess_token());
		pf.write("access_token_deadTime", access_token_deadTime);

		return access_token;
	}

	/**
	 * 获取微信jsapi_ticket
	 * 
	 * @param
	 * @return jsapi_ticket
	 * @throws Exception
	 */
	public static String getJsapiTicket() {
		PropertyFile pf = new PropertyFile();
		String jsapi_ticket = pf.read("jsapi_ticket");
		String jsapi_ticket_deadTime = pf.read("jsapi_ticket_deadTime");

		Date deadTime = DateUtil.strToDate(jsapi_ticket_deadTime);
		long times = DateUtil.remainDateToStringOther(new Date(), deadTime);
		// System.out.println("=========>times:" + times);
		// jsapi_ticket已过期
		if (times <= 0) {
			WechatJsapiTicket jt = refreshJsapiTicket();
			jsapi_ticket = jt.getTicket();
		}

		return jsapi_ticket;
	}

	/**
	 * 刷新微信jsapi_ticket
	 * 
	 * @param
	 * @return jsapi_ticket
	 * @throws Exception
	 */
	public static WechatJsapiTicket refreshJsapiTicket() {
		// 调用接口获取jsapi_ticket
		String access_token = getAccessToken();
		String jtUrl = WechatConfig.JSAPI_TICKET_URL + "&access_token="
				+ access_token;
		String resJSON = HttpRequestSimple.getInstance().getSendHttp(jtUrl);
		JSONObject reqObj = JSON.parseObject(resJSON);
		WechatJsapiTicket jt = new WechatJsapiTicket();
		jt.setTicket(reqObj.getString("ticket"));
		jt.setExpires_in(reqObj.getString("expires_in"));

		// 计算jsapi_ticket过期日期
		int expires_in = Convert.strToInt(jt.getExpires_in(), 0);
		Date deadTime = DateUtil.dateAddSecond(new Date(), expires_in);
		String jsapi_ticket_deadTime = DateUtil.dateToString(deadTime);

		// 存储jsapi_ticket信息
		PropertyFile pf = new PropertyFile();
		pf.write("jsapi_ticket", jt.getTicket());
		pf.write("jsapi_ticket_deadTime", jsapi_ticket_deadTime);

		return jt;
	}

	public static void main(String[] args) {
		
	}

}
